/*******************************************************************************
MPLAB Harmony Application Source File
Company:
Microchip Technology Inc.
File Name:
app.c
Summary:
This file contains the source code for the MPLAB Harmony application.
Description:
This file contains the source code for the MPLAB Harmony application. It
implements the logic of the application's state machine and it may call
API routines of other MPLAB Harmony modules in the system, such as drivers,
system services, and middleware. However, it does not call any of the
system interfaces (such as the "Initialize" and "Tasks" functions) of any of
the modules in the system or make any assumptions about when those functions
are called. That is the responsibility of the configuration-specific system
files.
*******************************************************************************/
// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved.
Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).
You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.
SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END
// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************
#include "system_definitions.h"
#include "app.h"
#include "stdio.h"
APP_DATA appData;
char Buf[32];
#define APP_MAKE_BUFFER_DMA_READY __attribute__ ((coherent, aligned(16))) //16バイト単位で配置
uint8_t receiveDataBuffer[64] APP_MAKE_BUFFER_DMA_READY; //受信バッファー
uint8_t transmitDataBuffer[64] APP_MAKE_BUFFER_DMA_READY; //送信バッファー
DRV_HANDLE myHandle;
bool LED;
unsigned short AdcValue;
float Volt;
int delay_Clock = 200000000; //システムクロック:200MHz
void delay_us(volatile unsigned int usec) //1μsec遅延
{
volatile int count;
count = (int)(delay_Clock/20000000)*usec;
do //実測 at 200MH (Clock=200000000)
{ //delay_us(1000):1000.4μsec delay_us(100):100.6μsec delay_us(10):10.5μsec delay_us(1):1.5μsec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");
count--;
}while(count != 0);
}
void delay_ms(volatile unsigned int msec) //1msec遅延
{
volatile unsigned int i; //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec delay_ms(100):100.04msec
for(i=0; i<msec; i++)
delay_us(1000);
}
void tmrISR(uintptr_t context, uint32_t alarmCount ) //タイマ1コールバック関数
{
//AD変換開始 Trigger a conversion
PLIB_ADCHS_GlobalSoftwareTriggerEnable(ADCHS_ID_0);//変換開始(グローバルソフトウェアエッジトリガの場合)
//ADCCON3bits.GSWTRG = 1; //変換開始(グローバルソフトウェアエッジトリガの場合)
//Trigger conversion for ADC inputs that have selected the GSWTRG bit as the trigger signal, either
//through the associated TRGSRC<4:0> bits in the ADCTRGx registers or through the STRGSRC<4:0>
//bits in the ADCCON1 register
//Class1 の場合、"ADCCON1bits.STRGSRC = 0; //スキャン開始トリガなし変換が終了する”(default)にすると
//変換終了後、自動的にサンプリングが実行される。
// 変換完了を待つ Wait the conversions to complete
// AN45 //AN0
while(!PLIB_ADCHS_AnalogInputDataIsReady(ADCHS_ID_0,ADCHS_AN0));
// while (ADCDSTAT1bits.ARDY0 == 0);
//結果の取り出し fetch the result
AdcValue = PLIB_ADCHS_AnalogInputResultGet(ADCHS_ID_0, ADCHS_AN0 );
// AdcValue = ADCDATA0;
/* //AN45
while (ADCDSTAT1bits.ARDY0 == 0);
//結果の取り出し fetch the result
AdcValue45 = ADCDATA0;
*/
};
void BufferRW(void)
{
appData.hidDataTransmitted = false;
/* Prepare the USB module to send the data packet to the host */
USB_DEVICE_HID_ReportSend (USB_DEVICE_HID_INDEX_0,
&appData.txTransferHandle, appData.transmitDataBuffer, 64 );
appData.hidDataReceived = false;
/* Place a new read request. */
USB_DEVICE_HID_ReportReceive (USB_DEVICE_HID_INDEX_0,
&appData.rxTransferHandle, appData.receiveDataBuffer, 64 );
}
void ConnectCheck(void) //接続確認応答
{
appData.transmitDataBuffer[2] = 'R';
appData.transmitDataBuffer[3] = 'e';
appData.transmitDataBuffer[4] = 'a';
appData.transmitDataBuffer[5] = 'd';
appData.transmitDataBuffer[6] = 'y';
BufferRW();
}
void LedOnOff(void) //LED点灯/消灯制御
{
switch(appData.receiveDataBuffer[1])
{
case 0x30: //RG15 //LED1
if(appData.receiveDataBuffer[2] == 0x30)
{
LATGbits.LATG15 = 0; //RG15 消灯
appData.transmitDataBuffer[2] = 0x30;
}
else
{
LATGbits.LATG15 = 1; //RG15 点灯
appData.transmitDataBuffer[2] = 0x31;
}
BufferRW();
break;
default :
break;
}
}
void SwDetect(void) //スイッチの状態検出
{
if(appData.receiveDataBuffer[1] == 0x31) //RB0
{
if(PORTBbits.RB0 == 0)appData.transmitDataBuffer[2] = 0x30;
else appData.transmitDataBuffer[2] = 0x31;
}
BufferRW();
}
void VR_Detect(void) //可変抵抗器VRの電圧検出
{
float Volt;
appData.transmitDataBuffer[2] = AdcValue; //下位8ビット at 12ビット
appData.transmitDataBuffer[3] = ((AdcValue >> 8) & 0b00001111); //上位4ビット摘出 at 12ビット
BufferRW();
Volt = (float)AdcValue/4096*3.3;
lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ
sprintf(Buf,"AdcValue=%d ",AdcValue);
lcd_ACM1602_str_i2c(Buf);
lcd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ
sprintf(Buf,"Volt=%.3f ",Volt);
lcd_ACM1602_str_i2c(Buf);
}
// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************
//
///* Recieve data buffer */
//uint8_t receiveDataBuffer[64] APP_MAKE_BUFFER_DMA_READY;
//
///* Transmit data buffer */
//uint8_t transmitDataBuffer[64] APP_MAKE_BUFFER_DMA_READY;
// *****************************************************************************
/* Application Data
Summary:
Holds application data
Description:
This structure holds the application's data.
Remarks:
This structure should be initialized by the APP_Initialize function.
Application strings and buffers are be defined outside this structure.
*/
//APP_DATA appData;
// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
USB_DEVICE_HID_EVENT_RESPONSE APP_USBDeviceHIDEventHandler
(
USB_DEVICE_HID_INDEX iHID,
USB_DEVICE_HID_EVENT event,
void * eventData,
uintptr_t userData
)
{
USB_DEVICE_HID_EVENT_DATA_REPORT_SENT * reportSent;
USB_DEVICE_HID_EVENT_DATA_REPORT_RECEIVED * reportReceived;
/* Check type of event */
switch (event)
{
case USB_DEVICE_HID_EVENT_REPORT_SENT:
/* The eventData parameter will be USB_DEVICE_HID_EVENT_REPORT_SENT
* pointer type containing details about the report that was
* sent. */
reportSent = (USB_DEVICE_HID_EVENT_DATA_REPORT_SENT *) eventData;
if(reportSent->handle == appData.txTransferHandle )
{
// Transfer progressed.
appData.hidDataTransmitted = true;
}
break;
case USB_DEVICE_HID_EVENT_REPORT_RECEIVED:
/* The eventData parameter will be USB_DEVICE_HID_EVENT_REPORT_RECEIVED
* pointer type containing details about the report that was
* received. */
reportReceived = (USB_DEVICE_HID_EVENT_DATA_REPORT_RECEIVED *) eventData;
if(reportReceived->handle == appData.rxTransferHandle )
{
// Transfer progressed.
appData.hidDataReceived = true;
}
break;
case USB_DEVICE_HID_EVENT_SET_IDLE:
/* For now we just accept this request as is. We acknowledge
* this request using the USB_DEVICE_HID_ControlStatus()
* function with a USB_DEVICE_CONTROL_STATUS_OK flag */
USB_DEVICE_ControlStatus(appData.usbDevHandle, USB_DEVICE_CONTROL_STATUS_OK);
/* Save Idle rate recieved from Host */
appData.idleRate = ((USB_DEVICE_HID_EVENT_DATA_SET_IDLE*)eventData)->duration;
break;
case USB_DEVICE_HID_EVENT_GET_IDLE:
/* Host is requesting for Idle rate. Now send the Idle rate */
USB_DEVICE_ControlSend(appData.usbDevHandle, & (appData.idleRate),1);
/* On successfully reciveing Idle rate, the Host would acknowledge back with a
Zero Length packet. The HID function drvier returns an event
USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT to the application upon
receiving this Zero Length packet from Host.
USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT event indicates this control transfer
event is complete */
break;
default:
// Nothing to do.
break;
}
return USB_DEVICE_HID_EVENT_RESPONSE_NONE;
}
void APP_USBDeviceEventHandler(USB_DEVICE_EVENT event, void * eventData, uintptr_t context)
{
switch(event)
{
case USB_DEVICE_EVENT_RESET:
case USB_DEVICE_EVENT_DECONFIGURED:
/* Host has de configured the device or a bus reset has happened.
* Device layer is going to de-initialize all function drivers.
* Hence close handles to all function drivers (Only if they are
* opened previously. */
appData.deviceConfigured = false;
appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
break;
case USB_DEVICE_EVENT_CONFIGURED:
/* Set the flag indicating device is configured. */
appData.deviceConfigured = true;
/* Save the other details for later use. */
appData.configurationValue = ((USB_DEVICE_EVENT_DATA_CONFIGURED*)eventData)->configurationValue;
/* Register application HID event handler */
USB_DEVICE_HID_EventHandlerSet(USB_DEVICE_HID_INDEX_0, APP_USBDeviceHIDEventHandler, (uintptr_t)&appData);
break;
case USB_DEVICE_EVENT_SUSPENDED:
/* Switch on green and orange, switch off red */
break;
case USB_DEVICE_EVENT_POWER_DETECTED:
/* VBUS was detected. We can attach the device */
USB_DEVICE_Attach (appData.usbDevHandle);
break;
case USB_DEVICE_EVENT_POWER_REMOVED:
/* VBUS is not available */
USB_DEVICE_Detach(appData.usbDevHandle);
break;
/* These events are not used in this demo */
case USB_DEVICE_EVENT_RESUMED:
case USB_DEVICE_EVENT_ERROR:
default:
break;
}
}
// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************
/* TODO: Add any necessary local functions.
*/
// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************
/*******************************************************************************
Function:
void APP_Initialize ( void )
Remarks:
See prototype in app.h.
*/
void APP_Initialize ( void )
{
/* Place the App state machine in its initial state. */
appData.state = APP_STATE_INIT;
appData.usbDevHandle = USB_DEVICE_HANDLE_INVALID;
appData.deviceConfigured = false;
appData.txTransferHandle = USB_DEVICE_HID_TRANSFER_HANDLE_INVALID;
appData.rxTransferHandle = USB_DEVICE_HID_TRANSFER_HANDLE_INVALID;
appData.hidDataReceived = false;
appData.hidDataTransmitted = true;
appData.receiveDataBuffer = &receiveDataBuffer[0];
appData.transmitDataBuffer = &transmitDataBuffer[0];
ADCTRGMODEbits.SH0ALT = 1; //入力ポート変更: AN0 --> AN45
DRV_ADC0_Open();
DRV_ADC_Start();
lcd_ACM1602_init_i2c(); //I2Cインターフェース式液晶初期化
lcd_ACM1602_cmd_i2c(0x0C); //カーソル:0FF、ブリンク:0FF
lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ
lcd_ACM1602_str_i2c("USB device HID ");
delay_ms(1000);
lcd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ
lcd_ACM1602_str_i2c(" Start !! ");
delay_ms(2000);
myHandle = DRV_TMR_Open ( DRV_TMR_INDEX_1, DRV_IO_INTENT_EXCLUSIVE );
//タイマ1ハンドル取得
uint32_t divider = 19532; //周期レジスタ初期値 //最初の割り込みまでの時間をセット
//10 nsec x 19532 x 256 = 50.00192msec = 50mec //PBCLK3のデフォルトは100MHz
DRV_TMR_AlarmRegister ( myHandle, divider, true, 0, tmrISR ); //繰り返し呼び出し
//コールバック関数繰り返し呼び出しをセットアップ
// bool DRV_TMR_AlarmRegister(
// DRV_HANDLE handle,
// uint32_t divider, //周期レジスタ初期値
// bool isPeriodic, //周期性の有無
// uintptr_t context,
// DRV_TMR_CALLBACK callBack
// );
DRV_TMR_Start(myHandle); //タイマ1割り込み許可、タイマ1イネーブル
}
/******************************************************************************
Function:
void APP_Tasks ( void )
Remarks:
See prototype in app.h.
*/
void APP_Tasks (void )
{
/* Check if device is configured. See if it is configured with correct
* configuration value */
switch(appData.state)
{
case APP_STATE_INIT:
/* Open the device layer */
appData.usbDevHandle = USB_DEVICE_Open( USB_DEVICE_INDEX_0, DRV_IO_INTENT_READWRITE );
if(appData.usbDevHandle != USB_DEVICE_HANDLE_INVALID)
{
/* Register a callback with device layer to get event notification (for end point 0) */
USB_DEVICE_EventHandlerSet(appData.usbDevHandle, APP_USBDeviceEventHandler, 0);
appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
}
else
{
/* The Device Layer is not ready to be opened. We should try
* again later. */
}
break;
case APP_STATE_WAIT_FOR_CONFIGURATION:
if(appData.deviceConfigured == true)
{
/* Device is ready to run the main task */
appData.hidDataReceived = false;
appData.hidDataTransmitted = true;
appData.state = APP_STATE_MAIN_TASK;
/* Place a new read request. */
USB_DEVICE_HID_ReportReceive (USB_DEVICE_HID_INDEX_0,
&appData.rxTransferHandle, appData.receiveDataBuffer, 64);
}
break;
case APP_STATE_MAIN_TASK:
if(!appData.deviceConfigured)
{
/* Device is not configured */
appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
}
else if( appData.hidDataReceived )
{
/* Look at the data the host sent, to see what
* kind of application specific command it sent. */
switch(appData.receiveDataBuffer[0]) //コマンドの種類判定
{
case 0x30: //接続確認応答
ConnectCheck();
break;
case 0x80: //LED点灯/消灯制御
LedOnOff();
break;
case 0x81: //スイッチの状態検出
SwDetect();
break;
case 0x82: //VR電圧検出
VR_Detect();
break;
default:
appData.hidDataReceived = false;
/* Place a new read request. */
USB_DEVICE_HID_ReportReceive (USB_DEVICE_HID_INDEX_0,
&appData.rxTransferHandle, appData.receiveDataBuffer, 64 );
break;
}
}
case APP_STATE_ERROR:
break;
default:
break;
}
}
/*******************************************************************************
End of File
*/